﻿/*
 ===================== 【MEA】讹诈 无人机 v1.0 发射平台控制程序（以FCS为目标来源，兼容FCS v6.5以上版本）  ================
 说明：
 1、填写好FCS编程块和杓鹬导弹编程块名字，直接运行或随意下达一个指令来激活。不需要定时块。本程序会带着FCS一起开机，无需额外触发FCS
 2、通过[Left]、[Right]、[Enter]三个指令来控制这个计算机，使用[Init]指令可清除所有已经离开的无人机，这也会让它们失效。
 3、可选[Up]、[Down]两个指令用来处理多导弹显示的上下翻页
 4、你也可以通过快速指令直接操控无人机，直接运行快速指令，母船会控制一架非该命令状态的无人机执行该命令
	快速指令包括：
	[Attack] 攻击
	[Sentry] 警戒
	[Die] 神风攻击
	[Wing] 伴飞
	[Dock] 停泊
	[Stop] 停止
	
 【注意】
 由于官方的BUG，造成从蓝图读取出来的整个系统无法正常工作。修复方法如下：
 当一个安装好的新系统从蓝图中粘贴出来后，先运行本编程块，然后再选中本编程块，选择点击[重置代码]按钮，然后再运行本编程块，就可以顺利使用了。
*/

/*
 通讯协议：
 本程序由中控计算机控制，并传输目标信息
 标准指令格式：EZ@1指令@2目标座标@3目标速度@4目标半径 [飞船序号]
 指令：
 Attack @ 目标座标 @ 目标速度 @ 目标 
 Wing
 Dock
*/

string MissileFirstName = "EZ"; //指令识别码（导弹只接受识别码正确的指令，不同型号的导弹或无人机程序使用不同的识别码）
string CockpitNameTag = "Cockpit"; //控制座椅名字，唯一
string FCSComputerNameTag = "FCS_Computer"; //火控雷达编程块名字
string LCDNameTag = "Missile_LCD"; //LCD名字，只支持宽屏LCD
string MissileComputerNameTag = "EZ_Computer";//讹诈无人机弹体编程块名称

IMyShipController Cockpit;
List<IMyTextPanel> LCD;

int t;
bool init;

List<string> tsaa = new List<string>();
void Main(string arguments)
{
	if(!init)
	{
		Runtime.UpdateFrequency = UpdateFrequency.Update1; //激活自触发  
		Cockpit = GridTerminalSystem.GetBlockWithName(CockpitNameTag) as IMyShipController;
		LCD = new List<IMyTextPanel>();
		GridTerminalSystem.GetBlocksOfType(LCD, b => b.CustomName == LCDNameTag);
		FCSComputer = GridTerminalSystem.GetBlockWithName(FCSComputerNameTag) as IMyProgrammableBlock;
		FCSComputer.TryRun("");
		if(FCSComputer == null)
		{
			HaveFoundTarget=false;
			Echo("Not Found FCS");
			return;
		}
		if(Cockpit==null)
		{
			Echo("Not Found Cockpit");
			return;
		}
		else if(LCD.Count < 1)
		{
			Echo("Not Found LCD");
			return;
		}
		else
		{
			Echo("Init Success");
			init = true;
		}
		return;
	}
	
	//快速指令
	if(arguments == "Attack"){
		for(int i = 0; i < MissileCommands.Count; i ++){
			if(MissileCommands[i] != "Attack"){
				MissileCommands[i] = "Attack";
				break;
			}
		}
	}
	if(arguments == "Sentry"){
		for(int i = 0; i < MissileCommands.Count; i ++){
			if(MissileCommands[i] != "Sentry"){
				MissileCommands[i] = "Sentry";
				break;
			}
		}
	}
	if(arguments == "Die"){
		for(int i = 0; i < MissileCommands.Count; i ++){
			if(MissileCommands[i] != "Die"){
				MissileCommands[i] = "Die";
				break;
			}
		}
	}
	if(arguments == "Wing"){
		for(int i = 0; i < MissileCommands.Count; i ++){
			if(MissileCommands[i] != "Wing"){
				MissileCommands[i] = "Wing";
				break;
			}
		}
	}
	if(arguments == "Dock"){
		for(int i = 0; i < MissileCommands.Count; i ++){
			if(MissileCommands[i] != "Dock"){
				MissileCommands[i] = "Dock";
				break;
			}
		}
	}
	if(arguments == "Stop"){
		for(int i = 0; i < MissileCommands.Count; i ++){
			if(MissileCommands[i] != "Stop"){
				MissileCommands[i] = "Stop";
				break;
			}
		}
	}
	
	t++;
	GetMissiles();
	GetTarget();
	MainOS(arguments);
	
	UpdataMissileTarget();

	ShowLCD();
}

// ======== 更新获取的导弹编程块 ==========
List<IMyTerminalBlock> MissileComputer;
List<string> MissileCommands;
List<Vector3D> MissileTargetPosition;
List<Vector3D> MissileTargetVelocity;
bool isFistGetMissile = true;
void GetMissiles()
{
	List<IMyTerminalBlock> missile_computer_temp = new List <IMyTerminalBlock>();
	GridTerminalSystem.SearchBlocksOfName(MissileComputerNameTag, missile_computer_temp);
	if(isFistGetMissile)
	{
		//初始化导弹弹体编程块相关
		MissileComputer = new List <IMyTerminalBlock>();
		MissileCommands = new List <string>();
		MissileTargetPosition = new List <Vector3D>();
		MissileTargetVelocity = new List <Vector3D>();
		for(int i = 0; i < missile_computer_temp.Count; i++)
		{
			MissileComputer.Add(missile_computer_temp[i]);
			MissileCommands.Add("Hold");
			MissileTargetPosition.Add(new Vector3D());
			MissileTargetVelocity.Add(new Vector3D());
		}
		isFistGetMissile = false;
	}
	else
	{
		for(int i = 0; i < missile_computer_temp.Count; i++){
			bool isThis = false;
			for(int j = 0; j < MissileComputer.Count; j++){
				if(missile_computer_temp[i] == MissileComputer[j]){
					isThis = true;
				}
			}
			if(!isThis){
				MissileComputer.Add(missile_computer_temp[i]);
				MissileCommands.Add("Hold");
				MissileTargetPosition.Add(new Vector3D());
				MissileTargetVelocity.Add(new Vector3D());
			}
		}
	}
	//检测损毁
	for(int i = 0; i < MissileComputer.Count; i ++){
		if(!MissileComputer[i].IsFunctional)
		{
			MissileComputer.Remove(MissileComputer[i]);
			MissileCommands.Remove(MissileCommands[i]);
			MissileTargetPosition.Remove(MissileTargetPosition[i]);
			MissileTargetVelocity.Remove(MissileTargetVelocity[i]);
		}
	}
}

// ========== 从FCS获取目标　===========
IMyProgrammableBlock FCSComputer;
string FCSCommands;
bool HaveFoundTarget;
long TargetID;
string TargetName;
double TargetDiameter;
Vector3D TargetPosition;
Vector3D TargetVelocity;
Vector3D TargetAcceleration;
void GetTarget()
{
	FCSCommands = FCSComputer.CustomData.Split('$')[1];
	string TargetInfo = FCSComputer.CustomData.Split('$')[2];
	TargetID = long.Parse(TargetInfo.Split('@')[0]);
	TargetName = TargetInfo.Split('@')[1];
	TargetDiameter = double.Parse(TargetInfo.Split('@')[2]);
	Vector3D.TryParse(TargetInfo.Split('@')[3],out TargetPosition);
	Vector3D.TryParse(TargetInfo.Split('@')[4],out TargetVelocity);
	Vector3D.TryParse(TargetInfo.Split('@')[5],out TargetAcceleration);
	if(TargetID != 0)
	{
		HaveFoundTarget = true;
	}
	else
	{
		HaveFoundTarget = false;
	}
}

//按键输入控制指令函数
// 菜单设计：
// 0开关火控扫描、1发射一枚、2齐射、3停止、4搜素范围、5发射时间、6自旋量、7制导系数
int OSX;
int OSY = -1;
void MainOS(string cmd)
{
	switch (cmd)
	{
	case ("Left"):
		if(OSX > 0)
		{OSX -= 1;}
		break;
	case ("Right"):
		if(OSX < 5)
		{OSX += 1;}
		break;
	case ("Up"):
		if(OSY > -1)
		{OSY -= 1;}
		break;
	case ("Down"):
		if(OSY < MissileComputer.Count-1)
		{OSY += 1;}
		break;
	case ("Enter"):
		if(OSX==0)
		{
			if(OSY == -1){CommondChange(-1, "Attack");}
			else{CommondChange(OSY, "Attack");}
		}
		else if(OSX==1)
		{
			if(OSY == -1){CommondChange(-1, "Sentry");}
			else{CommondChange(OSY, "Sentry");}
		}
		else if(OSX==2)
		{
			if(OSY == -1){CommondChange(-1, "Die");}
			else{CommondChange(OSY, "Die");}
		}
		else if(OSX==3)
		{
			if(OSY == -1){CommondChange(-1, "Wing");}
			else{CommondChange(OSY, "Wing");}
		}
		else if(OSX==4)
		{
			if(OSY == -1){CommondChange(-1, "Dock");}
			else{CommondChange(OSY, "Dock");}
		}
		else if(OSX==5)
		{
			if(OSY == -1){CommondChange(-1, "Stop");}
			else{CommondChange(OSY, "Stop");}
		}
		break;
	case ("Init"):
		init = false;
		isFistGetMissile = true;
		break;
	}
}

//-----改变无人机指令------ 传入-1表示全部
void CommondChange(int m, string CMD)
{
	if(m==-1)
	{
		for(int i = 0; i < MissileComputer.Count; i ++)
		{
			MissileCommands[i] = CMD;
		}
	}
	else
	{
		MissileCommands[m] = CMD;
	}
}

//负责根据导弹的指令给导弹传入正确的目标参数
void UpdataMissileTarget()
{
	for(int i = 0; i < MissileComputer.Count; i++)
	{
		string CMD = MissileFirstName + "@" + MissileCommands[i] + "@";
		CMD += TargetPosition.ToString() + "@";
		CMD += TargetVelocity.ToString() + "@";
		CMD += TargetDiameter.ToString() + "@";
		if(MissileCommands[i] != "Hold" && MissileComputer[i] != null)
		{
			IMyProgrammableBlock computer = MissileComputer[i] as IMyProgrammableBlock;
			CMD += "[" + i + "]";
			computer.TryRun(CMD);
		}
		Me.CustomData = CMD;
	}
}

void ShowLCD()
{
	string info = "";
	string br = "\n";
	info += sp("=",8) + " [ MEA ] 讹诈无人机系统 " + sp("=",9) + br;
	info += sp(" ",2) + "导弹" + sp(" ",8) + "指令" + sp(" ",8) + "状态" + sp(" ",8) + "距离(敌/我)" + br;
	int maxcontentline = 6; //中部内容版块最大显示行数
	int startnumber = 0; //开始行数
	int endnumber = 0; //结束行数
	//处理翻页的问题
	startnumber = 0;
	endnumber = MissileComputer.Count;
	if(OSY > maxcontentline - 1)
	{
		startnumber = OSY - maxcontentline + 1;
	}
	if(startnumber >= OSY + 1)
	{
		startnumber = OSY + 1;
	}
	if(maxcontentline < MissileComputer.Count)
	{
		endnumber = startnumber + maxcontentline;
	}
	
	//全体
	info += sp(" ",3) + (OSY==-1 ? "[ 选择全部 ]" : "  选择全部  ") + br;
	//输出目标清单
	for(int i = startnumber; i < endnumber; i ++)
	{
		info += sp(" ",3) + (OSY==i ? "[ " + i + " ]": "  " + i + "  ") + sp(" ",9) + MissileCommands[i] +
		        sp(" ",9) + (MissileComputer[i].IsFunctional?"正常":"损毁") +
		        sp(" ",9);
		if(MissileCommands[i] == "Attack" || MissileCommands[i] == "Die"){
			info += (HaveFoundTarget ? Math.Round(Vector3D.Distance(MissileComputer[i].GetPosition(),TargetPosition),2).ToString() : " - ") + br;
		}
		else{
			info += (Math.Round(Vector3D.Distance(MissileComputer[i].GetPosition(),Cockpit.GetPosition()),2).ToString()) + br;
		}
	}
	for(int i = 0; i < maxcontentline - MissileComputer.Count - 1; i ++) //中部内容区补空行
	{
		info += br;
	}
	//输出导弹信息结束
	info += sp("-",60) + br;
	info += br + sp(" ",2) + SS("攻击",OSX==0) + sp(" ",2) + SS("警卫",OSX==1) + sp(" ",2) + SS("自杀攻击",OSX==2);
	info += br + sp(" ",2) + SS("伴飞",OSX==3) + sp(" ",2) + SS("停泊",OSX==4) + sp(" ",2) + SS("停止",OSX==5);
	foreach(IMyTextPanel lcd in LCD){
		lcd.ShowPublicTextOnScreen();
		lcd.WritePublicText(info);
	}
}
string SS(string info, bool isSelect)
{
	string rt = "";
	if(isSelect)
	{
		rt = "[ " + info + " ]";
	}
	else
	{
		rt = "  " + info + "  ";
	}
	return rt;
}
string sp(string input,int x)
{
	string rt = "";
	for(int i = 0; i < x; i ++)
	{
		rt += input;
	}
	return rt;
}
string PP(double input,int length)
{
	string rt = input.ToString();
	if(rt.Length < length)
	{
		for(int i = 0; i < (length-rt.Length); i ++)
		{
			rt += " ";
		}
	}
	return rt;
}